package jp.yyoo.guitertuner;

import java.nio.ShortBuffer;

import jp.yyoo.guitertuner.MainProgram.Callback;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.widget.TextView;
import android.support.v4.app.NavUtils;

public class MainActivity extends Activity implements Callback {

	public static String TAG = "MainActivity";
	
	MainProgram program;
	
	
	
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        
    	Log.e(TAG, "onCreate");
    	
    	super.onCreate(savedInstanceState);
        setupWindow();
        
        
        setContentView(R.layout.activity_main);
        init();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
    
    
    @Override
    protected void onStart() {
    	Log.e(TAG, "onStart");
    	super.onStart();
    	
    }
    
    @Override
    protected void onStop() {
    	Log.e(TAG, "onStop");
    	super.onStop();
    }
    
    @Override
    protected void onResume() {
    	Log.e(TAG, "onResume");
    	super.onResume();

    	start();
    }
    
    @Override
    protected void onPause() {
    	Log.e(TAG, "onPause");
    	stop();
    	super.onPause();
    	
    }
    
    @Override
    public void onLowMemory() {
    	Log.e(TAG, "onLowMemory");
    	super.onLowMemory();
    }
    
    @Override
    protected void onDestroy() {
    	Log.e(TAG, "onDestroy");
    	super.onDestroy();
    }
    
    
    
    
    private void setupWindow() {

        requestWindowFeature(Window.FEATURE_NO_TITLE);
    	
    }
    
    
    private SurfaceView view;
    
    private DrawerThread thread;
    
    private void init() {
    	
    	thread = new DrawerThread( this );
    	thread.start();
    	view = (SurfaceView)findViewById( R.id.surface );
    	view.getHolder().addCallback( thread );
    	
    	/*
    	TextView comment = (TextView)findViewById( R.id.comment );
    	comment.setText( "init" );
    	*/
    	program = new MainProgram( this );
    	
    	program.setCallback( this );
    	
    	workingBuffer = ShortBuffer.allocate( MainProgram.frame_size*2 );
    	
    	paint = new Paint();
    	paint.setColor( Color.rgb(255, 0, 0) );
    }
    
    ShortBuffer workingBuffer;
    
    public void onReadCallback(short[] buffer) {
    	//Log.e(TAG, "onReadCallback");
    	synchronized (workingBuffer ) {
        	workingBuffer.position(0);
        	workingBuffer.put( buffer );
		}
    }
    
    private Paint paint;
    private Path path;
    
    private float[] points = new float[ MainProgram.frame_size*2 * 2 ];
    
    public void onDrawCallback( Canvas canvas ) {
    	
    	if( workingBuffer.limit()<=0 )return;
    	
    	//Log.e(TAG, "onDrawCallback");
    	
    	float width = canvas.getWidth();
    	float height = canvas.getHeight();
    	
    	path = new Path();
    	path.moveTo( 0, height / 2);
    	
    	
    	
    	synchronized ( workingBuffer ) {
    		
    		short[] buffer = workingBuffer.array();
			
    		int length = MainProgram.frame_size;
    		for( int i = 0; i < length; i++ ) {
    			short value = buffer[i];
    			//value-=300;
    			float tmp = ( (float) (-1*20*value) - Short.MIN_VALUE) / ((int)Short.MAX_VALUE * 2);
    			
    			//points[i*2] = i;
    			//points[i*2 + 1] = height * tmp;
    			
    			path.lineTo( width * ((float)(i + 1) / length ), height * tmp );
    		}

    		path.lineTo( width, height / 2 );
		}
    	
    	//canvas.drawPoints( points, paint);

    	canvas.drawColor( Color.argb(255,0,0,0) );
    	canvas.drawPath(path, paint);
    	
    }
    
    private void start() {
    	
    	program.start();
    	
    	thread.startDrawing();
    }
    
    private void stop() {

    	thread.stopDrawing();
    	program.stop();
    	
    }
    
    class DrawerThread extends Thread implements SurfaceHolder.Callback {
    	
    	
    	SurfaceHolder holder;
    	
    	int FPS = 60;
    	

		boolean flag;
		
		Object mutex;
		
		Object holderMutex;
		
		MainActivity callback;
		
		public DrawerThread( MainActivity callback_ ) {
			mutex = this;
			holderMutex = new Object();
			flag = false;
			callback = callback_;
		}
		
		public void startDrawing() {
			if( flag )return ;
			flag = true;
			synchronized (mutex) {
				mutex.notifyAll();
			}
		}
		
		public void stopDrawing() {
			flag = false;
		}
		
		boolean finalized = false;
		@Override
		protected void finalize() throws Throwable {
			
			finalized = true;
			super.finalize();
		}

		@Override
		public void run() {
			
			try {
				loop();
			} catch (Exception e) {
				Log.e( TAG, "error thread");
			}
		}
		
		private synchronized void loop() throws Exception{
			
			
			while( !finalized ) {
				
				if( !flag ) mutex.wait();
				
				if( holder == null ) synchronized (holderMutex) { holderMutex.wait();}
				
				Canvas canvas = holder.lockCanvas();

				callback.onDrawCallback( canvas );
				
				holder.unlockCanvasAndPost( canvas );
				
				sleep( 1000/FPS );
			}
		}
	    
	    public void surfaceChanged( SurfaceHolder holder_, int format, int width, int height) {
	    	holder = holder_;
	    }
	    public void surfaceCreated(SurfaceHolder holder_) {
	    	holder = holder_;
	    	synchronized (holderMutex) {
		    	holderMutex.notifyAll();
			}
	    }
	    public void surfaceDestroyed(SurfaceHolder holder_) {
	    	holder = null;

	    }
    }
    
}
